package cn.xinfei.xdecision.data.core.frame.executors.collect.handler;

import cn.xinfei.xdecision.common.model.datax.datainterface.v2.VarInterfaceInfo;
import cn.xinfei.xdecision.common.model.datax.datainterface.v2.VariableInterface;
import cn.xinfei.xdecision.common.model.datax.enums.CollectStageEnum;
import cn.xinfei.xdecision.common.service.datax.datainterface.v2.VarInterfaceInfoService;
import cn.xinfei.xdecision.data.core.cache.VarInterfaceCache;
import cn.xinfei.xdecision.data.core.frame.executors.collect.VarHandler;
import cn.xinfei.xdecision.data.core.frame.executors.VarContext;
import cn.xinfei.xdecision.data.core.util.VarCacheUtils;
import cn.xinfei.xdecision.data.core.vo.VarCollectAwareVO;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.common.utils.CollectionUtils;
import lombok.extern.slf4j.Slf4j;

import org.apache.commons.collections4.MapUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class VarFreeDataSourceHandler implements VarHandler<VarCollectAwareVO> {

    @Autowired
    VarInterfaceInfoService varInterfaceInfoService;

    @Autowired
    VarInterfaceCache varInterfaceCache;


    @Override
    public void doHandle(VarContext<VarCollectAwareVO> context) {
        VarCollectAwareVO collectRequestVO = context.get();
        collectRequestVO.setCollectStageEnum(CollectStageEnum.PRE_COLLECT);
        Set<String> varCodes = collectRequestVO.getVarCodes();
        Set<String> freeVars = new HashSet<>();
        Optional<Map<Integer, VarInterfaceInfo>> varInterfaceMetaDataCache = Optional.ofNullable(varInterfaceCache.loadVarInterfaceMetaData());

        Optional<List<VariableInterface>> varInterfaceRelMetaDataCache = Optional.ofNullable(varInterfaceCache.loadVarInterfaceRelMetaData());
        Map<String, List<String>> freeApiAndVarsMap;
        if (varInterfaceMetaDataCache.isPresent()
                && varInterfaceRelMetaDataCache.isPresent()) {
            log.info("requestId = {} VarFreeDataSourceHandler 查询缓存 VarInterfaceCache", JSONObject.toJSONString(collectRequestVO.getRequestId()));
            Map<Integer, Integer> dataSourceIdAndFreeFlagMap = varInterfaceMetaDataCache.get().values()
                    .stream()
                    .filter(varInter -> varInter.getIsCharge().equals(0))
                    .distinct()
                    .collect(Collectors.toMap(
                            VarInterfaceInfo::getId, VarInterfaceInfo::getIsCharge, (e1, e2) -> e1
                    ));
            List<Long> dataSourceIdsByVarCodes = varInterfaceRelMetaDataCache.get()
                    .stream()
                    .filter(Objects::nonNull)
                    .filter(var -> varCodes.contains(var.getVariableCode()))
                    .map(VariableInterface::getDatasourceId)
                    .distinct()
                    .map(Long::valueOf)
                    .filter(item -> Objects.nonNull(dataSourceIdAndFreeFlagMap.get(item.intValue()))
                            && dataSourceIdAndFreeFlagMap.get(item.intValue()) == 0)
                    .collect(Collectors.toList());
            freeApiAndVarsMap = VarCacheUtils.getApiAndVarsFeeAttrDataSourcesFromCache(varCodes, dataSourceIdsByVarCodes, varInterfaceRelMetaDataCache);

        } else {
            freeApiAndVarsMap = varInterfaceInfoService.selectFreeApiAndVarsByVarCodes(varCodes);

        }
        if (MapUtils.isEmpty(freeApiAndVarsMap)) {
            log.info("requestId = {} freeApiAndVarsMap is empty!", JSONObject.toJSONString(collectRequestVO.getRequestId()));
        } else {
            freeVars = freeApiAndVarsMap
                    .values().stream().flatMap(Collection::stream)
                    .filter(Objects::nonNull)
                    .collect(Collectors.toSet());
            Map<String, List<String>> filterFreeApiAndVarsMap = freeApiAndVarsMap.entrySet().stream().filter(entry ->
                    CollectionUtils.isNotEmpty(entry.getValue())).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
            log.info("requestId = {},freeApiAndVarsMap: {} freeVars: {}",
                    JSONObject.toJSONString(collectRequestVO.getRequestId()),
                    JSONObject.toJSONString(filterFreeApiAndVarsMap),
                    JSONObject.toJSONString(freeVars));
        }
        collectRequestVO.setVarCodes(freeVars);
        collectRequestVO.setApiVariablesMap(freeApiAndVarsMap);
        context.setContext(collectRequestVO);
    }

}
